package com.arpa.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.ntocc.common.common.cache.AreaCache;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.ntocc.common.domain.enums.CustomerCheckStatusEnum;
import com.arpa.wms.cache.SupplierCache;
import com.arpa.wms.common.util.UUIDUtil;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.dto.SupplierDTO;
import com.arpa.wms.domain.dto.SupplierFormDTO;
import com.arpa.wms.domain.entity.ExpenseDetail;
import com.arpa.wms.domain.entity.Shop;
import com.arpa.wms.domain.entity.Supplier;
import com.arpa.wms.domain.enums.ExpenseDetailStatusEnum;
import com.arpa.wms.domain.vo.SupplierVO;
import com.arpa.wms.mapper.SupplierMapper;
import com.arpa.wms.service.ISupplierService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.arpa.wms.domain.consts.TipConst.*;

/**
 * <p>
 * 供应商 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-09-04
 */
@Service
public class SupplierServiceImpl extends ServiceImpl<SupplierMapper, Supplier> implements ISupplierService {


    private final SupplierCache supplierCache;


    private final PartyCache partyCache;

    private final AreaCache areaCache;

    public SupplierServiceImpl(SupplierCache supplierCache, PartyCache partyCache, AreaCache areaCache) {
        this.supplierCache = supplierCache;
        this.partyCache = partyCache;
        this.areaCache = areaCache;
    }


    /**
     * 保存
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean save(Supplier entity) {

        SupplierDTO dto = new SupplierDTO();
        dto.setSupplierCode(entity.getSupplierCode());
        List<SupplierVO> codes = queryByNameOrCode(dto);
        if (null != codes && codes.size() > 0) {
            throw new ServiceException(SUPPLIER_CODE_EXIST);
        }
        dto.setSupplierCode("");
        dto.setName(entity.getName());
        List<SupplierVO> names = queryByNameOrCode(dto);
        if (null != names && names.size() > 0) {
            throw new ServiceException(SUPPLIER_NAME_EXIST);
        }
        if (StringUtils.isBlank(entity.getCode())) {
            entity.setCode(IdUtil.simpleUUID());
        }
        if (StringUtils.isBlank(entity.getCreatedBy())) {
            entity.setCreatedBy(UserUtil.getCode());
        }
        entity.setCode(UUIDUtil.getUUID32());
        entity.setCreatedBy(UserUtil.getCode());
        supplierCache.flushAllCacheByGroupCode(UserUtil.getBranchCode());
        return super.save(entity);
    }

    /**
     * 保存
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean save(SupplierFormDTO dto) {
        Supplier entity = new Supplier();
        BeanUtil.copyProperties(dto,entity );
        List<String> areaList = dto.getAreaList();
        if (IterUtil.isNotEmpty(areaList)&&areaList.size()==4) {
            entity.setCountry(areaList.get(0));
            entity.setProvince(areaList.get(1));
            entity.setCity(areaList.get(2));
            entity.setCounty(areaList.get(3));
        }

        int count = baseMapper.selectCount(new QueryWrapper<Supplier>().lambda().eq(Supplier::getSupplierCode, entity.getSupplierCode()).eq(Supplier::getGroupCode,UserUtil.getBranchCode()));
        if (count > 0) {
            throw new ServiceException(SUPPLIER_CODE_EXIST);
        }
        count = baseMapper.selectCount(new QueryWrapper<Supplier>().lambda().eq(Supplier::getName, entity.getName()).eq(Supplier::getGroupCode,UserUtil.getBranchCode()));
        if (count > 0) {
            throw new ServiceException(SUPPLIER_NAME_EXIST);
        }

        entity.setStatus(0);
        entity.setCode(UUIDUtil.getUUID32());
        entity.setCreatedBy(UserUtil.getCode());
        entity.setModifiedBy(UserUtil.getCode());
        entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
        entity.setCreatedName(partyCache.translate(UserUtil.getCode()));
        entity.setGroupCode(UserUtil.getBranchCode());
        supplierCache.flushAllCacheByGroupCode(UserUtil.getBranchCode());
        return super.save(entity);
    }

    /**
     * 根据code更新实体
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public int updateByCode(Supplier entity) {
        if(entity.getStatus()==2){
            entity.setStatus(0);
        }
        SupplierDTO dto = new SupplierDTO();
        dto.setSupplierCode(entity.getSupplierCode());
        List<SupplierVO> codes = queryByNameOrCode(dto);
        if (null != codes && codes.size() > 0) {
            SupplierVO supplierVO = codes.get(0);
            if (!supplierVO.getCode().equals(entity.getCode())) {
                throw new ServiceException(SUPPLIER_CODE_EXIST);
            }
        }
        dto.setSupplierCode("");
        dto.setName(entity.getName());
        Supplier supplier = baseMapper.selectOne(new QueryWrapper<Supplier>().lambda().eq(Supplier::getName, entity.getName()).eq(Supplier::getGroupCode,UserUtil.getBranchCode()));
        if (ObjectUtil.isNotNull(supplier)) {
            if (!StrUtil.equalsAny(entity.getCode(), supplier.getCode())) {
                throw new ServiceException(SUPPLIER_NAME_EXIST);
            }
        }
        if (StringUtils.isBlank(entity.getModifiedBy())) {
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
        }
        supplierCache.flushCache(entity.getCode());
        return baseMapper.update(entity, new QueryWrapper<Supplier>().lambda().eq(Supplier::getCode, entity.getCode()).eq(Supplier::getGroupCode,UserUtil.getBranchCode()));
    }    /**
     * 根据code更新实体
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public int updateByCode(SupplierFormDTO entity) {
        Supplier supplier = baseMapper.selectOne(new QueryWrapper<Supplier>().lambda().eq(Supplier::getCode, entity.getCode()).eq(Supplier::getGroupCode,UserUtil.getBranchCode()));
        Optional.ofNullable(supplier).orElseThrow(() -> new ServiceException("查不到供应商信息"));


        CopyOptions copyOptions = new CopyOptions();
        copyOptions.setIgnoreNullValue(true);
        BeanUtil.copyProperties(entity,supplier,copyOptions);



        List<String> areaList = entity.getAreaList();
        if (IterUtil.isNotEmpty(areaList)&&areaList.size()==4) {
            supplier.setCountry(areaList.get(0));
            supplier.setProvince(areaList.get(1));
            supplier.setCity(areaList.get(2));
            supplier.setCounty(areaList.get(3));
        }
        supplier.setModifiedBy(UserUtil.getCode());
        supplier.setModifiedName(partyCache.translate(UserUtil.getCode()));
        supplierCache.flushCache(entity.getCode());
        return  updateByCode(supplier);
    }



    /**
     * 查询列表
     *
     * @param supplierDTO
     * @return
     */
    @Override
    public List<SupplierVO> queryList(SupplierDTO supplierDTO) {
        //排序字段名需要驼峰转数据库下划线类型字段名
        if (StringUtils.isNotEmpty(supplierDTO.getSortField())) {
            supplierDTO.setSortField(CommonUtil.camel2Underline(supplierDTO.getSortField()));
            if ("status_text".equals(supplierDTO.getSortField())){
                supplierDTO.setSortField("a.status");
            }
        }
        List<SupplierVO> supplierVOList = baseMapper.queryList(supplierDTO);

        supplierVOList.forEach(e->{
            CustomerCheckStatusEnum enumByCode = CustomerCheckStatusEnum.getEnumByCode(e.getStatus());
            if (null != enumByCode) {
                e.setStatusText(enumByCode.getDesc());
            }
        });
        return supplierVOList;
    }
    private static String fetchGroupKey(Supplier supplier) {
        return supplier.getGroupCode();
    }
    @Override
    public List<SupplierVO> queryByNameOrCode(SupplierDTO supplierDTO) {
        supplierDTO.setGroupCode(UserUtil.getBranchCode());
        return baseMapper.queryByNameOrCode(supplierDTO);
    }

    /**
     * 查询合计,包含总数
     *
     * @param supplierDTO
     * @return
     */
    @Override
    public SupplierVO queryListSum(SupplierDTO supplierDTO) {
        SupplierVO supplierVO = baseMapper.queryListSum(supplierDTO);
        return supplierVO;
    }

    @Override
    public int batchDelete(List<String> codes, String modifiedBy) {
        codes.forEach(supplierCache::flushCache);
        return baseMapper.batchDelete(codes, modifiedBy);
    }

    /**
     * 模糊查询供应商
     *
     * @param keywords 关键字
     * @return
     */
    @Override
    public List<Map<String, Object>> search(String keywords) {

        List<Map<String, Object>> suppliers = supplierCache.getAllByGroupCode(UserUtil.getBranchCode());
        if (IterUtil.isNotEmpty(suppliers)) {
            // 过滤时，通过关键字，并且是已审核通过的
            if (StrUtil.isNotBlank(keywords)) {
                suppliers = suppliers.stream().filter(r -> NumConst.NUM_ONE.equals(r.get("status"))&&((StringUtils.containsAny(MapUtil.getStr(r, "name"), keywords)
                        || StringUtils.containsAny(MapUtil.getStr(r, "supplierCode"), keywords)
                        || StringUtils.containsAny(MapUtil.getStr(r, "phone"), keywords)))
                ).collect(Collectors.toList());
            } else {
                suppliers = suppliers.stream().filter(r -> NumConst.NUM_ONE.equals(r.get("status"))).collect(Collectors.toList());
            }
        }
        return suppliers;
    }

    @Override
    public SupplierVO getOneInfo(String code) {
        Supplier entity = baseMapper.selectOne(new QueryWrapper<Supplier>().lambda().eq(Supplier::getCode,code).eq(Supplier::getGroupCode,UserUtil.getBranchCode()));
        Optional.ofNullable(entity).orElseThrow(() -> new ServiceException("没有查询到信息"));
        SupplierVO supplierVO = new SupplierVO();
        BeanUtil.copyProperties(entity, supplierVO);
        List<String> areaList = new ArrayList<>();
        areaList.add(entity.getCountry());
        areaList.add(entity.getProvince());
        areaList.add(entity.getCity());
        areaList.add(entity.getCounty());
        String areaStr = "";
        if (StrUtil.isNotBlank(entity.getCountry())) {
            areaStr = areaCache.translateCountry(entity.getCountry());
        }

        if (StrUtil.isNotBlank(entity.getProvince())) {
            if (StrUtil.isNotBlank(areaStr)) {
                areaStr = areaStr + "/" + areaCache.translateProvince(entity.getProvince());
            } else {
                areaStr = areaCache.translateProvince(entity.getProvince());
            }
        }
        if (StrUtil.isNotBlank(entity.getCity())) {
            if (StrUtil.isNotBlank(areaStr)) {
                areaStr = areaStr + "/" + areaCache.translateCity(entity.getCity());
            } else {
                areaStr = areaCache.translateCity(entity.getCity());
            }
        }
        if (StrUtil.isNotBlank(entity.getCounty())) {
            if (StrUtil.isNotBlank(areaStr)) {
                areaStr = areaStr + "/" + areaCache.translateCounty(entity.getCounty());
            } else {
                areaStr = areaCache.translateCounty(entity.getCounty());
            }
        }
        supplierVO.setArea(areaStr);


        supplierVO.setAreaList(areaList);
        return supplierVO;
    }


}
